package ldh.im.fxgui.controller.sub;

import com.jfoenix.controls.JFXDialog;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import ldh.im.fxbase.data.pojo.ImGroup;
import ldh.im.fxbase.data.pojo.ImGroupUser;
import ldh.im.fxbase.data.pojo.ImSession;
import ldh.im.fxbase.data.pojo.ImUser;
import ldh.im.fxbase.util.*;
import ldh.im.fxgui.util.UiUtil;
import ldh.im.fxgui.util.UserHeadImageUtil;
import org.fxmisc.flowless.Cell;
import org.fxmisc.flowless.VirtualFlow;
import org.kordamp.ikonli.fontawesome.FontAwesome;
import org.kordamp.ikonli.javafx.FontIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class SelectGroupUserController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(SelectGroupUserController.class);

    @FXML private StackPane userPane;
    @FXML private FlowPane selectUserPane;
    @FXML private ScrollPane selectUserScrollPane;
    @FXML private TextField searchTextField;

    private JFXDialog dialog;
    private ObservableList<ImGroupUser> items = FXCollections.observableArrayList();
    private FilteredList<ImGroupUser> filteredData = new FilteredList<>(items, s -> true);
    private SortedList<ImGroupUser> sortedList = new SortedList<>(filteredData, this::userComparator);
    private VirtualFlow<ImGroupUser, ?> userList;

    private Set<ImGroupUser> selectImUsers = new HashSet<>();
    private Map<Long, Pane> selectPaneMap = new HashMap<>();

    private Map<Long, RadioButton> initSelectedUserMap = new HashMap<>();

    private Consumer<Set<ImGroupUser>> businessConsumer = null;

    public void setParams(JFXDialog dialog, ImSession currentImSession, Consumer<Set<ImGroupUser>> businessConsumer) {
        this.dialog = dialog;
        this.businessConsumer = businessConsumer;

        Set<ImGroupUser> imGroupUsers = currentImSession.getImGroup().getGroupUserSet();
        items.addAll(imGroupUsers);

        if (items.size() > 0) {
            userList.show(0);
        }

        String userId = UiUtil.getLoginImUser().getUserId();
        ImGroupUser groupUser = imGroupUsers.stream().filter(gu->gu.getUserId().equals(userId)).findAny().get();

        addSelectGroupUser(groupUser, null);
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        userList = VirtualFlow.createVertical(sortedList, m->{
            return Cell.wrapNode(createPane(m));
        });
        userPane.getChildren().add(userList);

        searchTextField.textProperty().addListener((InvalidationListener) l->{
            String filter = searchTextField.getText().trim();
            if(filter == null || filter.length() == 0) {
                filteredData.setPredicate(s -> true);
            } else {
                filteredData.setPredicate(s -> s.getUserName().contains(filter));
            }
        });
    }

    @FXML
    public void close(ActionEvent actionEvent) {
        dialog.close();
    }

    @FXML
    public void handleSelectedUsers(ActionEvent actionEvent) {
        if (selectImUsers.size() < 1) {
            DialogUtil.alert("提示", "请选择聊天人员");
            return;
        }

        businessConsumer.accept(selectImUsers);
        close(null);
    }

    private Node createPane(ImGroupUser groupUser) {
        LOGGER.info("createPane: {}", groupUser.getUserId());

        String userId = UiUtil.getLoginImUser().getUserId();
        HBox hBox = new HBox();
        hBox.getStyleClass().add("user-pane");
        RadioButton selectRadio = new RadioButton();

        boolean isSelected = false;
        if (groupUser.getUserId().equals(userId)) {
            isSelected = true;
            selectRadio.setSelected(true);
            selectRadio.setDisable(true);
        }

        if (!isSelected) {
            selectRadio.selectedProperty().addListener(l-> selectGroupUser(hBox, groupUser, selectRadio));

            hBox.setOnMouseClicked(e->{
                selectRadio.setSelected(!selectRadio.isSelected());
            });
        }

        if (selectImUsers.contains(groupUser)) {
            selectRadio.setSelected(true);
            hBox.getStyleClass().add("selected");
        }

        ImageView imageView = new ImageView();
        imageView.setFitHeight(40);
        imageView.setFitWidth(40);
        ImUser imUser = ImCacheFactory.getInstance().getUser(groupUser.getUserId());
        imageView.setImage(UserHeadImageUtil.getHeadImage(imUser.getHeadImg()));
        String name = groupUser.getUserName();
        if (StringUtil.isEmpty(name)) {
            name = imUser.getUserName();
        }
        Label tipLabel = new Label(name);
        tipLabel.setTooltip(new Tooltip(groupUser.getUserName()));
        hBox.getChildren().addAll(selectRadio, imageView);
        hBox.getChildren().add(tipLabel);

        initSelectedUserMap.put(groupUser.getId(), selectRadio);

        return hBox;
    }

    private void selectGroupUser(HBox hBox, ImGroupUser groupUser, RadioButton selectRadio) {
        if (selectRadio.isSelected()) {
            if (selectImUsers.contains(groupUser)) return;
            addSelectGroupUser(groupUser, selectRadio);
            hBox.getStyleClass().add("selected");
        } else if(selectImUsers.contains(groupUser)){
            Pane pane = selectPaneMap.get(groupUser.getId());
            selectUserPane.getChildren().remove(pane);
            selectImUsers.remove(groupUser);
            hBox.getStyleClass().remove("selected");
            return;
        }
    }

    private void addSelectGroupUser(ImGroupUser groupUser, RadioButton selectRadio) {
        ImUser imUser = ImCacheFactory.getInstance().getUser(groupUser.getUserId());
        ImageView imageView = new ImageView(UserHeadImageUtil.getHeadImage(imUser.getHeadImg()));
        imageView.setFitWidth(50);
        imageView.setFitHeight(50);
        Label label = new Label(imUser.getUserName());
        label.setTooltip(new Tooltip(imUser.getUserName()));
        label.setGraphic(imageView);
        label.setMaxSize(50, 70);
        label.setPrefSize(50, 70);
        label.setContentDisplay(ContentDisplay.TOP);

        StackPane stackPane = new StackPane(label);
        stackPane.setUserData(imUser);
        if (selectRadio != null) {
            FontIcon fontIcon = FontIcon.of(FontAwesome.CLOSE);
            fontIcon.setIconColor(Color.LIGHTGRAY);
            stackPane.getChildren().add(fontIcon);
            StackPane.setAlignment(fontIcon, Pos.TOP_RIGHT);

            fontIcon.setOnMouseEntered(e-> fontIcon.setIconColor(Color.GRAY));
            fontIcon.setOnMouseExited(e-> fontIcon.setIconColor(Color.LIGHTGRAY));
            fontIcon.setOnMouseClicked(e->{
                selectRadio.setSelected(false);
            });
        }

        selectUserPane.getChildren().add(stackPane);
        selectUserScrollPane.setVvalue(1);
        selectImUsers.add(groupUser);
        selectPaneMap.put(groupUser.getId(), stackPane);
    }

    private int userComparator(ImGroupUser imUser1, ImGroupUser imUser2) {
        if (imUser1.getUpdateTime() == null) return -1;
        if (imUser2.getUpdateTime() == null) return 1;
        return imUser1.getUpdateTime().compareTo(imUser2.getUpdateTime());
    }
}
